﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;

namespace K2AlgoExtensions
{
    /// <summary>
    /// Provide basic strategy handling - clients overide the functions
    /// that are specific to them
    /// </summary>
    public class ORAlgBase : KaiTrade.Interfaces.ORStrategyAlgorithm
    {
        protected KaiTrade.Interfaces.ORAlgCompleted m_ORAlgCompleted;

        /// <summary>
        /// 
        /// </summary>
        private object m_CalcPosn = new object();

        /// <summary>
        ///  Strateg Name
        /// </summary>
        protected string m_Name = "";

        /// <summary>
        /// Strategy that is running the algo
        /// </summary>
        protected KaiTrade.Interfaces.Strategy m_Strategy;



        /// <summary>
        /// If set to true - then updates to the orders controlled
        /// by this strategy will be ignored
        /// </summary>
        protected bool m_IgnoreUpdates = false;

        /// <summary>
        /// price difference when placing a stop order - if non zero
        /// a stop order will be placed to protect the initial order
        /// </summary>
        protected double m_StopDelta = 0.0;

        /// <summary>
        /// SpreadSize (profit target) tobe used on simple strategies
        /// </summary>
        protected double m_SpreadSize = 0.0;

        /// <summary>
        /// Timer for those algos that require some time based processing
        /// </summary>
        private System.Timers.Timer m_Timer;

        /// <summary>
        /// Timer interval used for the timer
        /// </summary>
        private long m_TimerInterval = 1000;

        private bool m_ExpireOrders = false;
        /// <summary>
        /// Time if specified that an order can be working before terminating
        /// </summary>
        private long m_ExpirationInterval = 0;

        /// <summary>
        /// Keeps count of how many time we have run the algo, between resets
        /// </summary>
        protected int m_RunCount = 0;

        /// <summary>
        /// Starting position - used to offset the actual position 
        /// </summary>
        private double m_StartPosition = 0;


        private string m_CorrelationID = "";

        /// <summary>
        /// List of order monitored by the algo - for example those to be canceled
        /// </summary>
        private List<KaiTrade.Interfaces.Order> m_MonitorList;

        /// <summary>
        /// Map of order ID's to legs - used for multileg products
        /// </summary>
        protected Dictionary<string, KaiTrade.Interfaces.Leg> m_OrderIDLeg;

        /// <summary>
        /// Map of Leg ID's to orders - used for multileg products
        /// </summary>
        //private Dictionary<string, KaiTrade.Interfaces.Order> m_LegIDOrder;

        /// <summary>
        /// Logger
        /// </summary>
        public log4net.ILog m_Log = log4net.LogManager.GetLogger("KaiAlgo");

        public ORAlgBase()
        {
            m_MonitorList = new List<KaiTrade.Interfaces.Order>();
            m_OrderIDLeg = new Dictionary<string, KaiTrade.Interfaces.Leg>();
            //m_LegIDOrder = new Dictionary<string, KaiTrade.Interfaces.Order>();

            ClearParameters();
        }

        /// <summary>
        /// Called on Set updates - used to allow clients to be evented when the alg completes
        /// </summary>
        public virtual KaiTrade.Interfaces.ORAlgCompleted ORAlgCompleted
        {

            get { return m_ORAlgCompleted; }
            set { m_ORAlgCompleted = value; }

        }

        public virtual string CorrelationID
        {

            get { return m_CorrelationID; }
            set { m_CorrelationID = value; }

        }



        public double SpreadSize
        {
            get { return m_SpreadSize; }
            set { m_SpreadSize = value; }
        }

        /// <summary>
        /// Starting position - used to offset the actual position 
        /// </summary>
        public double StartPosition
        {
            get { return m_StartPosition; }
            set { m_StartPosition = value; }
        }

        /// <summary>
        /// Get the position based on the strategy position and the start position
        /// a +ve value implies we are long and a -ve implies we are short
        /// </summary>
        /// <returns></returns>
        protected double GetAdjustedPosition()
        {
            double position = 0.0;
            try
            {
                position = m_Strategy.Position;
                position += this.StartPosition;
            }
            catch (Exception myE)
            {
                m_Log.Error("GetAdjustedPosition", myE);
            }
            return position;
        }

        /// <summary>
        /// Get the qty adjusted by the side (BUY => =ve) 
        /// and SELL => -ve
        /// </summary>
        /// <returns></returns>
        protected double GetSideAjustedQty()
        {
            double qty = 0.0;
            try
            {
                if (KaiUtil.QFUtils.isSell(m_Strategy.Side))
                {
                    qty = m_Strategy.Qty * -1;
                }
                else
                {
                    qty = m_Strategy.Qty;
                }

            }
            catch (Exception myE)
            {
                m_Log.Error("GetSideAjustedQty", myE);
            }
            return qty;
        }

        /// <summary>
        /// get the amount we need to buy or sell, a -ve qty => we must sell
        /// a +ve implies we need to buy - this based on the Qty and the start position
        /// </summary>
        /// <returns></returns>
        protected double GetAdjustedTargetQty()
        {
            double targetQty = 0.0;
            try
            {
                targetQty = GetSideAjustedQty();
                targetQty -= GetAdjustedPosition();

            }
            catch (Exception myE)
            {
                m_Log.Error("getTargetQty", myE);
            }
            return targetQty;
        }

        /// <summary>
        /// get/set timer interval - note this doen not change a running timer
        /// </summary>
        public long TimerInterval
        {
            get { return m_TimerInterval; }
            set { m_TimerInterval = value; }
        }

        /// <summary>
        /// Get/set if orders are expired
        /// </summary>
        public bool ExpireOrders
        {
            get { return m_ExpireOrders; }
            set
            {
                m_ExpireOrders = value;
                if (m_ExpireOrders)
                {
                    StartTimer();
                }
                else
                {
                    StopTimer();
                }
            }
        }

        public long ExpirationInterval
        {
            get { return m_ExpirationInterval; }
            set { m_ExpirationInterval = value; }
        }
        /// <summary>
        /// get the P&L for the strategy - calculated when accessed 
        /// not you need prices for this.
        /// </summary>
        public double GetPNL(KaiTrade.Interfaces.Strategy myStrategy)
        {
            double myPNL = 0.0;
            try
            {
                // iterate all orders
                KaiTrade.Interfaces.Order myOrd = null;
                foreach (string myOrdID in myStrategy.GetOrders())
                {
                    myOrd = Factory.Instance().AppFacade.Factory.GetOrderManager().GetOrder(myOrdID);
                    myPNL += myOrd.GetCurrentPNL();

                }
            }
            catch (Exception myE)
            {
                m_Log.Error("GetPNL", myE);
            }
            return myPNL;
        }
        /// <summary>
        /// Refresh the position of the Strategy, will iterate the orders to 
        /// total position
        /// </summary>
        public virtual void RefreshPosition(KaiTrade.Interfaces.Strategy myStrategy)
        {
            lock (m_CalcPosn)
            {
                try
                {
                    myStrategy.ShortWorkingQty = 0.0;
                    myStrategy.LongWorkingQty = 0.0;
                    myStrategy.ShortFilledQty = 0.0;
                    myStrategy.LongFilledQty = 0.0;
                    myStrategy.LongPotentialQty = 0.0;
                    myStrategy.ShortPotentialQty = 0.0;

                    // iterate all orders
                    KaiTrade.Interfaces.Order myOrd = null;
                    foreach (string myOrdID in myStrategy.GetOrders())
                    {
                        try
                        {
                            myOrd = Factory.Instance().AppFacade.Factory.GetOrderManager().GetOrder(myOrdID);
                            if (myOrd.Side.getValue() == QuickFix.Side.SELL)
                            {
                                if (myOrd.LeavesQty != null)
                                    myStrategy.ShortWorkingQty += myOrd.LeavesQty.getValue();
                                if (myOrd.CumQty != null)
                                    myStrategy.ShortFilledQty += myOrd.CumQty.getValue();
                                // only consider working orders
                                if (myOrd.IsWorking())
                                {
                                    myStrategy.ShortPotentialQty += myOrd.OrderQty.getValue();
                                }
                            }
                            else
                            {
                                if (myOrd.CumQty != null)
                                    myStrategy.LongFilledQty += myOrd.CumQty.getValue();
                                if (myOrd.LeavesQty != null)
                                    myStrategy.LongWorkingQty += myOrd.LeavesQty.getValue();
                                // only consider working orders
                                if (myOrd.IsWorking())
                                {
                                    myStrategy.LongPotentialQty += myOrd.OrderQty.getValue();
                                }
                            }
                        }
                        catch (Exception myE)
                        {
                            m_Log.Error("RefreshPosition:loop", myE);
                        }

                    }
                }
                catch (Exception myE)
                {
                    m_Log.Error("RefreshPosition", myE);
                }
            }
        }

        /// <summary>
        /// Cancel the strategy, all running orders are cancelled
        /// </summary>
        /// <param name="myStrategy"></param>
        /// <returns></returns>
        public virtual int Cancel(KaiTrade.Interfaces.Strategy myStrategy)
        {
            int myOrderModifiedCount = 0;
            try
            {
                // get each order in the strategy and try to cancel it
                List<string> myOrders = myStrategy.GetOrders();
                KaiTrade.Interfaces.Order myOrd;
                // track how many orders we modified


                foreach (string myOrdID in myOrders)
                {
                    try
                    {
                        //myOrd = Factory.Instance().AppFacade.Factory.GetOrderManager().GetOrder(myOrdID);
                        Factory.Instance().AppFacade.CancelOrder(myOrdID);
                        // track how many orders we modified
                        myOrderModifiedCount++;
                    }
                    catch (Exception myE)
                    {
                        m_Log.Warn("order casnnot be cancelled");
                    }


                }
            }
            catch (Exception myE)
            {
                m_Log.Error("doCancel", myE);
            }
            return myOrderModifiedCount;
        }

        public int CancelBuy(KaiTrade.Interfaces.Strategy myStrategy)
        {
            int myOrderModifiedCount = 0;
            try
            {
                // get each order in the strategy and try to cancel it
                List<string> myOrders = myStrategy.GetOrders();
                KaiTrade.Interfaces.Order myOrd;
                // track how many orders we modified


                foreach (string myOrdID in myOrders)
                {
                    myOrd = Factory.Instance().AppFacade.Factory.GetOrderManager().GetOrder(myOrdID);
                    if (myOrd.Side.getValue() == QuickFix.Side.BUY)
                    {

                        Factory.Instance().AppFacade.CancelOrder(myOrdID);
                        // track how many orders we modified
                        myOrderModifiedCount++;
                    }


                }
            }
            catch (Exception myE)
            {
                m_Log.Error("doCancelBuy", myE);
            }
            return myOrderModifiedCount;
        }
        public int CancelSell(KaiTrade.Interfaces.Strategy myStrategy)
        {
            int myOrderModifiedCount = 0;
            try
            {
                // get each order in the strategy and try to cancel it
                List<string> myOrders = myStrategy.GetOrders();
                KaiTrade.Interfaces.Order myOrd;
                // track how many orders we modified


                foreach (string myOrdID in myOrders)
                {
                    myOrd = Factory.Instance().AppFacade.Factory.GetOrderManager().GetOrder(myOrdID);
                    if (myOrd.Side.getValue() == QuickFix.Side.SELL)
                    {

                        Factory.Instance().AppFacade.CancelOrder(myOrdID);
                        // track how many orders we modified
                        myOrderModifiedCount++;
                    }


                }
            }
            catch (Exception myE)
            {
                m_Log.Error("doCancelBuy", myE);
            }
            return myOrderModifiedCount;
        }

        protected void SubmitOtherSide(KaiTrade.Interfaces.Strategy myStrategy, KaiTrade.Interfaces.Order myOrd, double myQty, double myPrice, string myOrderType, string extendedOrderType, List<KaiTrade.Interfaces.K2Parameter> parms)
        {
            try
            {
                double stopPx = 0.0;
                if (myOrd.StopPx != null)
                {
                    stopPx = myOrd.StopPx.getValue();
                }
                string myAccount = "";
                if (myOrd.Account != null)
                {
                    myAccount = myOrd.Account.getValue();
                }

                if (myOrd.Side.getValue() == QuickFix.Side.BUY)
                {
                    Submit(myStrategy, myOrd.OrderQty.getValue(), myOrd.OrderQty.getValue(), myPrice, stopPx, "Sell", myOrderType, "Day", "", myAccount, extendedOrderType, parms);
                }
                else
                {
                    Submit(myStrategy, myOrd.OrderQty.getValue(), myOrd.OrderQty.getValue(), myPrice, stopPx, "Buy", myOrderType, "Day", "", myAccount, extendedOrderType, parms);
                }
            }
            catch (Exception myE)
            {
                m_Log.Error("SubmitOtherSide", myE);
            }

        }

        protected void SubmitOtherSideMkt(KaiTrade.Interfaces.Strategy myStrategy, KaiTrade.Interfaces.Order myOrd, double myQty)
        {
            try
            {
                double myNewPrice = -1;
                if (myOrd.Price != null)
                {
                    myNewPrice = myOrd.Price.getValue();
                }
                SubmitOtherSide(myStrategy, myOrd, myQty, myNewPrice, KaiTrade.Interfaces.OrderType.MARKET, "", null);
            }
            catch (Exception myE)
            {
                m_Log.Error("SubmitOtherSideMkt", myE);
            }


        }

        /// <summary>
        /// Flatten/Trade out any positions of each order in the in the strategy
        /// CAUTION - Only knows orders from the strategy itself, if you trade
        /// orders out manually - DO NOT USE THIS
        /// </summary>
        /// <param name="myStrategy"></param>
        /// <returns></returns>
        public virtual int Flatten(KaiTrade.Interfaces.Strategy myStrategy)
        {
            int myFlattenCount = 0;
            try
            {
                // get each order in the strategy and try to flatten it
                List<string> myOrders = new List<string>();
                foreach (string myOrdID in myStrategy.GetOrders())
                {
                    myOrders.Add(myOrdID);
                }

                KaiTrade.Interfaces.Order myOrd;
                // track how many orders we modified

                foreach (string myOrdID in myOrders)
                {
                    try
                    {
                        myOrd = Factory.Instance().AppFacade.Factory.GetOrderManager().GetOrder(myOrdID);

                        // if the order is working - cancel it
                        if (myOrd.LeavesQty.getValue() > 0)
                        {
                            try
                            {
                                Factory.Instance().AppFacade.CancelOrder(myOrdID);
                            }
                            catch (Exception myE)
                            {
                            }
                        }

                        // use any filled qty to submit a market order on the other side
                        //if (myOrd.CumQty.getValue() > 0)
                        //{
                        //   SubmitOtherSideMkt(myStrategy, myOrd, myOrd.CumQty.getValue());
                        //}
                        myFlattenCount++;
                    }
                    catch (Exception myE)
                    {
                    }


                }
                double myPosition = myStrategy.LongFilledQty - myStrategy.ShortFilledQty;
                if (myPosition > 0)
                {
                    // we do not want derived classes to do the submit here - incase they provide unwanted additional functino
                    doSubmit(myStrategy, myPosition, myPosition, 99999999, 99999999, KaiTrade.Interfaces.Side.SELL, KaiTrade.Interfaces.OrderType.MARKET, KaiTrade.Interfaces.TimeType.DAY, "", myStrategy.Account, "", null);
                }
                else if (myPosition < 0)
                {
                    // we do not want derived classes to do the submit here - incase they provide unwanted additional functino
                    doSubmit(myStrategy, Math.Abs(myPosition), Math.Abs(myPosition), 0, 0, KaiTrade.Interfaces.Side.BUY, KaiTrade.Interfaces.OrderType.MARKET, KaiTrade.Interfaces.TimeType.DAY, "", myStrategy.Account, "", null);
                }
            }
            catch (Exception myE)
            {
                m_Log.Error("Flatten", myE);
            }
            return myFlattenCount;
        }

        /// <summary>
        /// Modify any working orders
        /// </summary>
        /// <param name="myStrategy"></param>
        /// <param name="newQty"></param>
        /// <param name="newPrice"></param>
        /// <returns>number of modified orders</returns>
        public virtual int Replace(KaiTrade.Interfaces.Strategy myStrategy, double? newQty, double? newPrice, double? newStopPx)
        {
            // check that external trading is enabled
            // track how many orders we modified
            int myOrderModifiedCount = 0;
            try
            {


                // get each order in the strategy and try to cancel it
                // if there are no orders working them we do a submit
                List<string> myOrders = myStrategy.GetOrders();
                KaiTrade.Interfaces.Order myOrd;



                foreach (string myOrdID in myOrders)
                {
                    try
                    {
                        KaiTrade.Interfaces.Order myStratOrd = Factory.Instance().AppFacade.Factory.GetOrderManager().GetOrder(myOrdID);
                        if (myStratOrd != null)
                        {
                            if (myStratOrd.IsWorking())
                            {
                                // if we have set ignore updates to true - then
                                // ignore this request to modify working orders
                                // if there are no working orders - then processing is not 
                                // changed
                                if (m_IgnoreUpdates)
                                {
                                    return (-1);
                                }
                                Factory.Instance().AppFacade.ReplaceOrder(myOrdID, newQty, newPrice, newStopPx);
                                myOrderModifiedCount++;
                            }
                        }
                    }
                    catch (Exception myE)
                    {
                        m_Log.Error("doReplace:loop", myE);
                    }
                }

            }
            catch (Exception myE)
            {
                m_Log.Error("doReplace", myE);
            }
            return myOrderModifiedCount;
        }


        protected void addOrder2Grp(KaiTrade.Interfaces.OrderGroup myGrp, string myOrderID)
        {
            try
            {
                KaiTrade.Interfaces.Order myOrder = Factory.Instance().AppFacade.Factory.GetOrderManager().GetOrder(myOrderID);
                if (myGrp == null)
                {
                }
                else
                {
                    myOrder.OrderGroup = myGrp;
                }
                myOrder.OrderGroup.AddOrder(myOrder);
            }
            catch (Exception myE)
            {
                m_Log.Error("addOrder2Grp", myE);
            }

        }

        protected void addOrder2Grp(KaiTrade.Interfaces.Strategy myStrategy, string myOrderID)
        {
            try
            {
                KaiTrade.Interfaces.Order myOrder = Factory.Instance().AppFacade.Factory.GetOrderManager().GetOrder(myOrderID);

                if (myOrder.OrderGroup == null)
                {
                    myOrder.OrderGroup = Factory.Instance().AppFacade.Factory.CreateOrderGroup();
                    // Need to track the groups in the strategy
                    myStrategy.AddOrderGroup(myOrder.OrderGroup);
                }
                myOrder.OrderGroup.AddOrder(myOrder);
            }
            catch (Exception myE)
            {
                m_Log.Error("addOrder2Grp", myE);
            }

        }

        public virtual string Submit(KaiTrade.Interfaces.Strategy myStrategy, KaiTrade.Interfaces.Order myOrder)
        {
            string myID = "";
            try
            {
                myID = myOrder.Identity;
                Factory.Instance().AppFacade.SubmitOrder(myOrder);
                myOrder.StrategyName = myStrategy.UserName;
                myOrder.ParentIdentity = myStrategy.Identity;
                myStrategy.AddOrder(myOrder);
                myStrategy.Side = myOrder.Side;
                myStrategy.OrdType = myOrder.OrdType;

            }
            catch (Exception myE)
            {
                m_Log.Error("Submit", myE);
            }
            return myID;

        }

        /// <summary>
        /// Submit the strategy based on the default parameters in the strategy
        /// </summary>
        /// <param name="myStrategy"></param>
        public virtual string Submit(KaiTrade.Interfaces.Strategy myStrategy)
        {
            string myID = "";
            try
            {
                if (myStrategy.PriceInValidRange(KaiUtil.QFUtils.DecodeOrderType(myStrategy.OrdType), myStrategy.Price))
                {
                    myID = doSubmit(myStrategy, myStrategy.Qty, myStrategy.QtyLimit, myStrategy.Price, myStrategy.StopPx, KaiUtil.QFUtils.DecodeSide(myStrategy.Side), KaiUtil.QFUtils.DecodeOrderType(myStrategy.OrdType), myStrategy.TimeInForce, myStrategy.TIFDateTime, myStrategy.Account, "", null);
                }
                else
                {
                    m_Log.Error("Submit: price outside valid range");
                }

            }
            catch (Exception myE)
            {
                m_Log.Error("doSubmit", myE);
            }

            return myID;
        }
        protected string SubmitStop(KaiTrade.Interfaces.Strategy myStrategy, KaiTrade.Interfaces.Order myOrder)
        {
            string myID = "";
            try
            {
                // if they specify a stop delta then do a stop order provided the incoming order is not already a Stop
                if ((m_StopDelta > 0.0) && (myOrder.OrdType.getValue() != QuickFix.OrdType.STOP) && (myOrder.OrdType.getValue() != QuickFix.OrdType.STOP_LIMIT))
                {
                    double myStopPx = -1;
                    double myPrice = -1;
                    if (myOrder.OrdType.getValue() == QuickFix.OrdType.MARKET)
                    {

                        QuickFix.LastPx myLastPx = myOrder.LastPx;

                        m_Log.Info("Order is Market - this fill px is:" + myLastPx.getValue().ToString());
                        myPrice = myLastPx.getValue();

                        myOrder.Price = new QuickFix.Price(myPrice);
                    }
                    else
                    {
                        myPrice = myOrder.Price.getValue();
                    }

                    string myStopSide = "";
                    switch (KaiUtil.QFUtils.DecodeSide(myOrder.Side).ToUpper())
                    {
                        case "SELL":
                            myStopSide = "Buy";
                            myStopPx = myPrice + m_StopDelta;
                            break;
                        case "BUY":
                            myStopSide = "Sell";
                            myStopPx = myPrice - m_StopDelta;
                            break;
                        default:
                            break;
                    }

                    myID = Factory.Instance().AppFacade.SubmitOrder(myStrategy.Identity, myOrder.Mnemonic, myOrder.OrderQty.getValue(),
                                                        myOrder.Price.getValue(), myStopSide, "Stop", myStopPx, "Day", "", myOrder.Account.getValue(), myStrategy.ShortSaleLocate, myStrategy.MaxFloor, myOrder.ExtendedOrdType, null);

                    KaiTrade.Interfaces.Order myStopOrder = Factory.Instance().AppFacade.Factory.GetOrderManager().GetOrder(myID);
                    if (this.ExpireOrders)
                    {
                        // work out expiration
                        myStopOrder.Expiration = (DateTime.Now.AddMilliseconds(this.ExpirationInterval)).Ticks;
                        m_MonitorList.Add(myStopOrder);
                    }

                    myStopOrder.StrategyName = myStrategy.UserName;
                    myStopOrder.ParentIdentity = myStrategy.Identity;
                    myStrategy.AddOrder(myStopOrder);
                    //myStrategy.Side = myOrder.Side;
                    //myStrategy.OrdType = myOrder.OrdType;
                }

            }
            catch (Exception myE)
            {
                m_Log.Error("Submit", myE);
            }
            return myID;

        }
        protected string SubmitMarketOrder(KaiTrade.Interfaces.Strategy myStrategy, KaiTrade.Interfaces.Order myOrder)
        {
            return SubmitMarketOrder(myStrategy, myOrder, KaiUtil.QFUtils.DecodeSide(myOrder.Side), myOrder.OrderQty.getValue());
        }

        protected string SubmitMarketOrder(KaiTrade.Interfaces.Strategy myStrategy, KaiTrade.Interfaces.Order myOrder, string mySide, double? myQty)
        {
            string myID = "";
            try
            {
                // if they specify a stop delta then do a stop order provided the incoming order is not already a Stop
                if ((myOrder.OrdType.getValue() != QuickFix.OrdType.MARKET))
                {
                    double myStopPx = -1;
                    double myPrice = -1;

                    myPrice = myOrder.Price.getValue();

                    myID = Factory.Instance().AppFacade.SubmitOrder(myStrategy.Identity, myOrder.Mnemonic, myQty.Value,
                                                        myOrder.Price.getValue(), mySide, KaiTrade.Interfaces.OrderType.MARKET, myStopPx, KaiTrade.Interfaces.TimeType.DAY, "", myOrder.Account.getValue(), myStrategy.ShortSaleLocate, myStrategy.MaxFloor, myOrder.ExtendedOrdType, null);

                    KaiTrade.Interfaces.Order myMarketOrder = Factory.Instance().AppFacade.Factory.GetOrderManager().GetOrder(myID);
                    if (this.ExpireOrders)
                    {
                        // work out expiration
                        myMarketOrder.Expiration = (DateTime.Now.AddMilliseconds(this.ExpirationInterval)).Ticks;
                        m_MonitorList.Add(myMarketOrder);
                    }

                    myMarketOrder.StrategyName = myStrategy.UserName;
                    myMarketOrder.ParentIdentity = myStrategy.Identity;
                    myStrategy.AddOrder(myMarketOrder);

                }

            }
            catch (Exception myE)
            {
                m_Log.Error("SubmitMarketOrder", myE);
            }
            return myID;

        }


        /// <summary>
        /// Do a order submit and record the order in the strategy - but do not use order groups
        /// </summary>
        /// <param name="myStrategy"></param>
        /// <param name="myQty"></param>
        /// <param name="myQtyLimit"></param>
        /// <param name="myPrice"></param>
        /// <param name="myStopPx"></param>
        /// <param name="mySide"></param>
        /// <param name="myOrderType"></param>
        /// <param name="myTimeType"></param>
        /// <param name="myDateTime"></param>
        /// <param name="myAccount"></param>
        /// <returns></returns>
        private string doSubmit(KaiTrade.Interfaces.Strategy myStrategy, double myQty, double myQtyLimit, double myPrice, double myStopPx, string mySide, string myOrderType, string myTimeType, string myDateTime, string myAccount, string extendedOrderType, List<KaiTrade.Interfaces.K2Parameter> parms)
        {
            string myID = "";
            try
            {
                if (myStrategy.PriceInValidRange(myOrderType, myPrice))
                {
                    // register the strategy with the publisher manager - so we can subscribe to 
                    // the strategy updates
                    KaiTrade.Interfaces.Publisher myPub = Factory.Instance().AppFacade.Factory.GetPublisherManager().GetPublisher(myStrategy.UserName);
                    if (myPub == null)
                    {
                        Factory.Instance().AppFacade.Factory.GetPublisherManager().Add(myStrategy as KaiTrade.Interfaces.Publisher);
                    }
                    myStrategy.Qty = myQty;
                    KaiTrade.Interfaces.TradableProduct myProduct = Factory.Instance().AppFacade.Factory.GetProductManager().GetProduct(myStrategy.ProductID);
                    if (myProduct != null)
                    {
                        if (myProduct.Legs.Count > 0)
                        {
                            // this product has legs so we need to submit each leg
                            foreach (KaiTrade.Interfaces.Leg myLeg in myProduct.Legs)
                            {
                                OrderLeg(myLeg, myStrategy, mySide, null, null, null);

                            }
                        }
                        else
                        {
                            //Submit this order
                            myID = doSubmit(myStrategy, myProduct, myQty, myQtyLimit, myPrice, myStopPx, mySide, myOrderType, myTimeType, myDateTime, myAccount, extendedOrderType, parms);

                        }

                    }
                    else
                    {
                        string myError = "Cannot place order - invalid product ID:" + myStrategy.ProductID;
                        Exception myE = new Exception(myError);
                        throw myE;
                    }
                }
                else
                {
                    string myError = "Cannot place order - price outside valid range:" + myPrice.ToString();
                    Exception myE = new Exception(myError);
                    throw myE;
                }
            }
            catch (Exception myE)
            {
                m_Log.Error("doSubmit", myE);
            }

            return myID;
        }

        protected void AssociateOrderProductLeg(KaiTrade.Interfaces.Order myOrder, KaiTrade.Interfaces.Leg myLeg)
        {
            try
            {
                m_OrderIDLeg.Add(myOrder.Identity, myLeg);
                //m_LegIDOrder.Add(myLeg.Identity, myOrder);
            }
            catch (Exception myE)
            {
                m_Log.Error("AssociateOrderProductLeg", myE);
            }
        }



        /// <summary>
        /// Submit an order based on a product leg - note that this will manage the
        /// order groups for each leg
        /// </summary>
        /// <param name="myLeg"></param>
        /// <param name="myStrategy"></param>
        /// <param name="mySide"></param>
        /// <param name="myBasePx">optionally, the price used to base the leg order - usually the fill price of a leading order</param>
        /// <returns>the ID of the submitted order</returns>
        protected virtual string OrderLeg(KaiTrade.Interfaces.Leg myLeg, KaiTrade.Interfaces.Strategy myStrategy, string mySide, double? myDesiredQty, double? myBasePx, double? myBaseOffset)
        {
            string myID = "";
            try
            {
                if (!myStrategy.Enabled)
                {
                    m_Log.Warn("Request to submit order leg on disabled strategy");
                    return "";
                }
                m_Log.Info("Order Leg:" + myLeg.Mnemonic);
                // do the first leg
                KaiTrade.Interfaces.OrderGroup myOrdGrp;
                KaiTrade.Interfaces.Order myOrd;
                if (myLeg.Product != null)
                {

                    double myQty;
                    // calculate the leg qty - its the leg qty * the strategy qty
                    if (myDesiredQty.HasValue)
                    {
                        myQty = Math.Min((double)myLeg.Quantity * myDesiredQty.Value, myStrategy.QtyLimit);
                    }
                    else
                    {

                        myQty = Math.Min((double)myLeg.Quantity * myStrategy.Qty, myStrategy.QtyLimit);
                    }
                    double myPrice = 0.0;
                    double myStopPx = 0.0;
                    //Submit this order
                    string myAcctCode = "";
                    if (myLeg.AccountCode.Length > 0)
                    {
                        myAcctCode = myLeg.AccountCode;
                    }
                    else
                    {
                        myAcctCode = myStrategy.Account;
                    }
                    // invert side as required - if the side passed in is BUY then use leg sides asis, otherwise we need to invert the side
                    // 
                    string myLegSide = "";
                    if (mySide.ToUpper() == KaiTrade.Interfaces.Side.BUY)
                    {
                        myLegSide = myLeg.Side;
                    }
                    else
                    {
                        myLegSide = Factory.Instance().AppFacade.Factory.GetOrderManager().InvertSide(myLeg.Side);
                    }
                    // figure out the price if they want a LIMIT order

                    if (myLeg.OrdType.ToUpper() == KaiTrade.Interfaces.OrderType.LIMIT)
                    {
                        switch (myLegSide.ToUpper())
                        {
                            case KaiTrade.Interfaces.Side.BUY:
                                if (myBasePx == null)
                                {
                                    myLeg.Price = myLeg.Product.L1PX.BidPrice - (myLeg.SpreadOffset);
                                }
                                else
                                {
                                    myLeg.Price = (decimal)myBasePx.Value - ((decimal)myBaseOffset.Value);
                                }
                                break;
                            case KaiTrade.Interfaces.Side.SELL:

                                if (myBasePx == null)
                                {
                                    myLeg.Price = myLeg.Product.L1PX.OfferPrice + (myLeg.SpreadOffset);
                                }
                                else
                                {
                                    myLeg.Price = (decimal)(myBasePx.Value + (myBaseOffset.Value));
                                }
                                break;
                            case KaiTrade.Interfaces.Side.SHORT:
                                if (myBasePx == null)
                                {
                                    myLeg.Price = myLeg.Product.L1PX.OfferPrice + (myLeg.SpreadOffset);
                                }
                                else
                                {
                                    myLeg.Price = (decimal)(myBasePx.Value + (myBaseOffset.Value));
                                }
                                break;
                                break;
                            default:
                                break;
                        }

                    }
                    else if (myLeg.OrdType.ToUpper() == KaiTrade.Interfaces.OrderType.STOP)
                    {
                        if (myBasePx == null)
                        {
                            throw new Exception("You must specify a STOP price");
                        }
                        myLeg.Price = -1;
                        myStopPx = myBasePx.Value;
                    }
                    myID = Factory.Instance().AppFacade.SubmitOrder(myStrategy.Identity, myLeg.Mnemonic, myQty, (double)myLeg.Price, myLegSide, myLeg.OrdType, myStopPx, "Day", "", myAcctCode, myStrategy.ShortSaleLocate, myStrategy.MaxFloor, "", null);

                    // set the user friendly name an the strategy ID as the parent in the order
                    myOrd = Factory.Instance().AppFacade.Factory.GetOrderManager().GetOrder(myID);

                    // Track the order ID to the leg used in ordering
                    AssociateOrderProductLeg(myOrd, myLeg);

                    myOrd.StrategyName = myStrategy.UserName;
                    myOrd.ParentIdentity = myStrategy.Identity;
                    myStrategy.AddOrder(myOrd);
                    //myStrategy.Side = myOrd.Side;
                    myStrategy.OrdType = myOrd.OrdType;

                    myStrategy.LastOrdIdentity = myID;
                    addOrder2Grp(myStrategy, myID);

                    // Keep a track of this order in a group of orders just for this leg
                    myStrategy.GetLegOrderGroup(myLeg.Identity).AddOrder(myOrd);
                    myStrategy.GetLegOrderGroup(myLeg.Identity).Tag = myLeg.Mnemonic;

                    // Submit a stop order if required
                    if (m_StopDelta > 0.0)
                    {
                        //this.SubmitStop(myStrategy, myOrd);
                        //myStrategy.LastOrdIdentity = myID;
                        //addOrder2Grp(myStrategy, myID);
                    }
                }
            }
            catch (Exception myE)
            {
                m_Log.Error("OrderLeg", myE);
            }
            return myID;
        }

        private string doSubmit(KaiTrade.Interfaces.Strategy myStrategy, KaiTrade.Interfaces.TradableProduct myProduct, double myQty, double myQtyLimit, double myPrice, double myStopPx, string mySide, string myOrderType, string myTimeType, string myDateTime, string myAccount, string extendedOrderType, List<KaiTrade.Interfaces.K2Parameter> parms)
        {
            string myID = "";
            try
            {

                // register the strategy with the publisher manager - so we can subscribe to 
                // the strategy updates
                KaiTrade.Interfaces.Publisher myPub = Factory.Instance().AppFacade.Factory.GetPublisherManager().GetPublisher(myStrategy.UserName);
                if (myPub == null)
                {
                    Factory.Instance().AppFacade.Factory.GetPublisherManager().Add(myStrategy as KaiTrade.Interfaces.Publisher);
                }

                if (myStrategy.PriceInValidRange(myOrderType, myPrice))
                {
                    if (myProduct != null)
                    {
                        if (myProduct.Legs.Count > 0)
                        {
                            // this product has legs so we need to submit each leg
                        }
                        else
                        {

                            //Submit this order
                            myID = Factory.Instance().AppFacade.SubmitOrder(myStrategy.Identity, myProduct.Mnemonic, myQty, myPrice, mySide, myOrderType, myStopPx, myTimeType, myDateTime, myAccount, myStrategy.ShortSaleLocate, myStrategy.MaxFloor, extendedOrderType, parms);

                            // set the user friendly name an the strategy ID as the parent in the order
                            KaiTrade.Interfaces.Order myOrd = Factory.Instance().AppFacade.Factory.GetOrderManager().GetOrder(myID);
                            myOrd.StrategyName = myStrategy.UserName;
                            myOrd.ParentIdentity = myStrategy.Identity;
                            myStrategy.AddOrder(myOrd);
                            if (this.ExpireOrders)
                            {
                                // work out expiration
                                myOrd.Expiration = (DateTime.Now.AddMilliseconds(this.ExpirationInterval)).Ticks;
                                m_MonitorList.Add(myOrd);
                            }

                            //myStrategy.Side = myOrd.Side;
                            //myStrategy.OrdType = myOrd.OrdType;
                            // Submit a stop order if required
                            /* do this in the exec report
                            if (m_StopDelta > 0.0)
                            {
                                this.SubmitStop(myStrategy, myOrd);
                                myStrategy.LastOrdIdentity = myID;
                                addOrder2Grp(myStrategy, myID);
                            }
                             * */
                        }


                    }
                    else
                    {
                        string myError = "Cannot place order - invalid product ID:" + myStrategy.ProductID;
                        Exception myE = new Exception(myError);
                        throw myE;
                    }
                }
                else
                {
                    string myError = "Cannot place order - price outside valid range:" + myPrice.ToString();
                    Exception myE = new Exception(myError);
                    throw myE;
                }
            }
            catch (Exception myE)
            {
                m_Log.Error("doSubmit", myE);
            }

            return myID;
        }
        /// <summary>
        /// Place order for the strategy - assumes a single leg product for now
        /// record the order in the strategy - but do not use order groups
        /// </summary>
        /// <param name="myQty"></param>
        /// <param name="myQtyLimit"></param>
        /// <param name="myPrice"></param>
        /// <param name="myStopPx"></param>
        /// <param name="mySide"></param>
        /// <param name="myOrderType"></param>
        /// <returns></returns>
        public virtual string Submit(KaiTrade.Interfaces.Strategy myStrategy, double myQty, double myQtyLimit, double myPrice, double myStopPx, string mySide, string myOrderType, string myTimeType, string myDateTime, string myAccount, string extendedOrderType, List<KaiTrade.Interfaces.K2Parameter> parms)
        {
            return doSubmit(myStrategy, myQty, myQtyLimit, myPrice, myStopPx, mySide, myOrderType, myTimeType, myDateTime, myAccount, extendedOrderType, parms);
        }


        public virtual void HandleExecReport(QuickFix.Message myExec, KaiTrade.Interfaces.Strategy myStrategy, KaiTrade.Interfaces.Order myOrd)
        {
            try
            {
                if ((myOrd.OrdType.getValue() == QuickFix.OrdType.STOP) || (myOrd.OrdType.getValue() == QuickFix.OrdType.STOP_LIMIT))
                {
                    // do not process STOP orders as part of this Algo
                    return;
                }
                if (myOrd.OrdStatus.getValue() == QuickFix.OrdStatus.FILLED)
                {
                    // If they want a stop for the leading order place it now
                    if (m_StopDelta > 0.0)
                    {
                        this.SubmitStop(myStrategy, myOrd);
                    }
                }
                // if this was a multi leg product submitted by the base alg
                // now get the leg's order group to do an update since we have an exec report that 
                // may have changed order positions
                if (m_OrderIDLeg.ContainsKey(myOrd.Identity))
                {
                    KaiTrade.Interfaces.Leg myOrdLeg = m_OrderIDLeg[myOrd.Identity];
                    KaiTrade.Interfaces.Publisher myLegGrpPub = myStrategy.GetLegOrderGroup(myOrdLeg.Identity) as KaiTrade.Interfaces.Publisher;
                    if (myLegGrpPub != null)
                    {
                        myLegGrpPub.OnUpdate(null);
                    }
                }
            }
            catch (Exception myE)
            {
                m_Log.Error("HandleExecReport", myE);
            }
        }

        public virtual void HandleReject(QuickFix.Message myReject, KaiTrade.Interfaces.Strategy myStrategy, KaiTrade.Interfaces.Order myOrd)
        {

        }

        public virtual void HandlePositionChange(KaiTrade.Interfaces.Strategy myStrategy)
        {

        }

        public virtual void Reset()
        {

        }

        /// <summary>
        /// Cancel and reverse out the position of a non comelete order group
        /// </summary>
        /// <param name="myGrp"></param>
        public void Flatten(KaiTrade.Interfaces.OrderGroup myGrp)
        {
            try
            {
                double myLongAmt = 0;
                double myShortAmt = 0;

                // First cancel any unfilled orders
                foreach (KaiTrade.Interfaces.Order myOrd in myGrp.Orders)
                {


                    if (myOrd.IsWorking())
                    {
                        Factory.Instance().AppFacade.CancelOrder(myOrd.Identity);
                    }

                    if (myOrd.Side.getValue() == QuickFix.Side.BUY)
                    {
                        myLongAmt = myOrd.CumQty.getValue();
                    }
                    else if (myOrd.Side.getValue() == QuickFix.Side.SELL)
                    {
                        myShortAmt = myOrd.CumQty.getValue();
                    }
                }

                // is there some remaining position
                double myGrpPos = myLongAmt - myShortAmt;
                if (myGrpPos > 0)
                {

                    // we are long so reverse out
                    // Do the Buy and then the Sell
                    string myOrdID = Submit(this.Strategy, Math.Abs(myGrpPos), Math.Abs(myGrpPos), -1, -1, KaiTrade.Interfaces.Side.SELL, KaiTrade.Interfaces.OrderType.MARKET, KaiTrade.Interfaces.TimeType.DAY, "", this.Strategy.Account, "", null);
                }
                else if (myGrpPos < 0)
                {

                    // we are long so reverse out
                    // Do the Buy and then the Sell
                    string myOrdID = Submit(this.Strategy, Math.Abs(myGrpPos), Math.Abs(myGrpPos), -1, -1, KaiTrade.Interfaces.Side.BUY, KaiTrade.Interfaces.OrderType.MARKET, KaiTrade.Interfaces.TimeType.DAY, "", this.Strategy.Account, "", null);
                }
            }
            catch (Exception myE)
            {
                m_Log.Error("Flatten", myE);
            }

        }

        /// <summary>
        /// Get/Set the strategy runing this algo
        /// </summary>
        public KaiTrade.Interfaces.Strategy Strategy
        {
            get { return m_Strategy; }
            set { m_Strategy = value; }
        }



        /// <summary>
        /// Start the algo running this may result in orders being placed
        /// </summary>
        public virtual void Run(KaiTrade.Interfaces.Strategy myStrategy)
        {
            if (m_RunCount < myStrategy.MaxIterations)
            {
                string myOrderID = this.Submit(myStrategy);
                myStrategy.LastOrdIdentity = myOrderID;
                m_RunCount++;
            }
        }


        /// <summary>
        /// Enter the strategy - action depends on implimenting class
        /// </summary>
        public virtual void Enter(KaiTrade.Interfaces.Strategy myStrategy)
        {
        }

        /// <summary>
        /// Exit the strategy - action depends on implimenting class
        /// </summary>
        public virtual void Exit(KaiTrade.Interfaces.Strategy myStrategy)
        {
            m_RunCount = 0;
        }

        /// <summary>
        /// Process a Trade signal
        /// </summary>
        /// <param name="myStrategy">strategy running the algo</param>
        /// <param name="isExitSignal">is the signal an exit-depends on the list of exists for the strategy</param>
        /// <param name="mySignal">a trade signal</param>
        public virtual void HandleTradeSignal(KaiTrade.Interfaces.Strategy myStrategy, bool isExitSignal, KaiTrade.Interfaces.TradeSignal mySignal)
        {
            // needs to be done by sub class
        }


        #region ORStrategyAlgorithm Members

        protected void AddStrategyParameters(K2AtdlTools.K2AtdlStrategyBuilder strategyBuilder)
        {
            try
            {
                strategyBuilder.AddParameter("Order", "Name", K2AtdlTools.ADTLType.String, 99, true, m_Strategy.UserName, "", "");

                strategyBuilder.SetGroupOrientation("Order", K2AtdlTools.LayOutOrientation.vertical);
                strategyBuilder.AddParameter("Order", "Mnemonic", K2AtdlTools.ADTLType.String, 99, true, m_Strategy.Mnemonic, "", "");
                strategyBuilder.AddParameter("Order", "Side", K2AtdlTools.ADTLType.String, 99, true, KaiUtil.QFUtils.DecodeSide(m_Strategy.Side), "", "");
                strategyBuilder.AddParameterEnum("Side", KaiTrade.Interfaces.Side.BUY, KaiTrade.Interfaces.Side.BUY, KaiTrade.Interfaces.Side.BUY);
                strategyBuilder.AddParameterEnum("Side", KaiTrade.Interfaces.Side.SELL, KaiTrade.Interfaces.Side.SELL, KaiTrade.Interfaces.Side.SELL);
                strategyBuilder.AddParameter("Order", "Price", K2AtdlTools.ADTLType.Float, 99, true, m_Strategy.Price.ToString(), "", "");
                strategyBuilder.AddParameter("Order", "Qty", K2AtdlTools.ADTLType.Int, 99, true, m_Strategy.Qty.ToString(), "", "");
                strategyBuilder.AddParameter("Base", "MaxEntries", K2AtdlTools.ADTLType.Int, 99, true, m_Strategy.MaxEntries.ToString(), "", "");
                strategyBuilder.AddParameter("Base", "MaxIterations", K2AtdlTools.ADTLType.Int, 99, true, m_Strategy.MaxIterations.ToString(), "", "");
                strategyBuilder.AddParameter("Base", "MinPrice", K2AtdlTools.ADTLType.Float, 99, true, m_Strategy.MinPrice.ToString(), "", "");
                strategyBuilder.AddParameter("Base", "MaxPrice", K2AtdlTools.ADTLType.Float, 99, true, m_Strategy.MaxPrice.ToString(), "", "");
                strategyBuilder.AddParameter("Base", "ExitOperation", K2AtdlTools.ADTLType.String, 99, true, "None", "", "");
                strategyBuilder.AddParameter("Base", "StartTime", K2AtdlTools.ADTLType.UTCTimeOnly, 99, true, m_Strategy.StartTime.ToString(), "", "");
                strategyBuilder.AddParameter("Base", "EndTime", K2AtdlTools.ADTLType.UTCTimeOnly, 99, true, m_Strategy.EndTime.ToString(), "", "");
                strategyBuilder.AddParameterEnum("ExitOperation", "FlattenOnExit", "e_FlattenOnExit", "flatten strategy on exit");
                strategyBuilder.AddParameterEnum("ExitOperation", "CancelOnExit", "e_CancelOnExit", "cancel working orders on exit");
                strategyBuilder.AddParameterEnum("ExitOperation", "None", "e_None", "no action");

            }
            catch (Exception myE)
            {
                m_Log.Error("addStrategyParameters", myE);
            }
        }
        /// <summary>
        /// Generate ATDL
        /// </summary>
        /// <returns></returns>
        public virtual string GetAtdl()
        {
            try
            {
                K2AtdlTools.K2AtdlBuilder builder = new K2AtdlTools.K2AtdlBuilder();
                K2AtdlTools.K2AtdlStrategyBuilder strategyBuilder = builder.AddStrategyBuilder("ORAlgBase", "ORAlgBase", "D", "KaiTrade LLC");

                AddStrategyParameters(strategyBuilder);
                if (m_Strategy != null)
                {
                    strategyBuilder.AddParameter("Algo", "Enabled", K2AtdlTools.ADTLType.Boolean, 99, true, m_Strategy.Enabled.ToString(), "", "");
                }
                else
                {
                    strategyBuilder.AddParameter("Algo", "Enabled", K2AtdlTools.ADTLType.Boolean, 99, true, false.ToString(), "", "");
                }
                strategyBuilder.AddParameter("Algo", "StopDelta", K2AtdlTools.ADTLType.Float, 99, true, m_StopDelta.ToString(), "", "");
                strategyBuilder.AddParameter("Algo", "IgnoreUpdates", K2AtdlTools.ADTLType.Boolean, 99, true, m_IgnoreUpdates.ToString(), "", "");
                strategyBuilder.AddParameter("Algo", "SpreadSize", K2AtdlTools.ADTLType.Float, 99, true, m_SpreadSize.ToString(), "", "");
                strategyBuilder.AddParameter("Algo", "ExpirationTime", K2AtdlTools.ADTLType.Int, 99, true, m_ExpirationInterval.ToString(), "", "");
                strategyBuilder.AddParameter("Algo", "ExpireOrders", K2AtdlTools.ADTLType.Boolean, 99, true, m_ExpireOrders.ToString(), "", "");


                strategyBuilder.AddDefaultLayout();

                return builder.GetAtdlAsString();
            }
            catch (Exception myE)
            {
                m_Log.Error("GetAtdl", myE);
            }
            return "";
        }

        public virtual void SetFromAtdl(string atdl)
        {
            try
            {
                com.kaitrade.core.Strategies strategies = new com.kaitrade.core.Strategies();
                strategies.FromXml(atdl);
                //SetStrategy(strategies.Strategy[0], title);
            }
            catch (Exception myE)
            {
                m_Log.Error("SetFromAtdl", myE);
            }
        }


        private void parseParameters(com.kaitrade.core.Strategy_t strategy)
        {
            try
            {
                foreach (com.kaitrade.core.IParameter_t parm in strategy.Parameter)
                {

                    SetParameterValue(parm.Name, "", DateTime.Now.Ticks.ToString());

                }
            }
            catch (Exception mye)
            {
            }
        }

        public virtual List<string> GetParameterNames()
        {
            List<string> myRet = new List<string>();
            //myRet.Add("SpreadSize");
            myRet.Add("StopDelta");
            myRet.Add("IgnoreUpdates");
            myRet.Add("SpreadSize");
            myRet.Add("ExpirationTime");
            myRet.Add("ExpireOrders");
            //myRet.Add("MaxRuns");
            return myRet;

        }

        public virtual string GetParameterValue(string myName)
        {
            string myRet = "";
            switch (myName)
            {

                case "StopDelta":
                    myRet = m_StopDelta.ToString();
                    break;
                case "IgnoreUpdates":
                    myRet = m_IgnoreUpdates.ToString();
                    break;
                case "SpreadSize":
                    myRet = m_SpreadSize.ToString();
                    break;
                case "ExpirationTime":
                    myRet = this.ExpirationInterval.ToString();

                    break;
                case "ExpireOrders":
                    myRet = this.ExpireOrders.ToString();

                    break;
                case "MaxRuns":
                    //myRet = this.ma

                    break;
                default:
                    break;
            }
            return myRet;
        }



        public string Name
        {
            get { return m_Name; }
        }

        /// <summary>
        /// Clear the algo parameters
        /// </summary>
        public virtual void ClearParameters()
        {
            m_StopDelta = 0;
            m_IgnoreUpdates = false;
            m_SpreadSize = 0;
            this.ExpireOrders = false;
            this.ExpirationInterval = 0;

        }

        public virtual void SetParameterValue(KaiTrade.Interfaces.K2Parameter parameter, string runIdentifier)
        {
            SetParameterValue(parameter.ParameterName, parameter.ParameterValue, runIdentifier);
        }


        public virtual void SetParameterValue(string myName, string myValue, string runIdentifier)
        {
            switch (myName)
            {

                case "StopDelta":
                    m_StopDelta = double.Parse(myValue);
                    break;
                case "IgnoreUpdates":
                    if (myValue.ToUpper() == "TRUE")
                    {
                        m_IgnoreUpdates = true;
                    }
                    else
                    {
                        m_IgnoreUpdates = false;
                    }
                    break;
                case "SpreadSize":
                    m_SpreadSize = double.Parse(myValue);
                    break;
                case "ExpireOrders":
                    if (myValue.ToUpper() == "TRUE")
                    {
                        this.ExpireOrders = true;
                    }
                    else
                    {
                        this.ExpireOrders = false;
                    }
                    break;
                case "ExpirationTime":
                    this.ExpirationInterval = long.Parse(myValue);
                    break;
                case "WaitTime":
                    this.ExpirationInterval = long.Parse(myValue);
                    break;
                case "StartPosition":
                    this.StartPosition = double.Parse(myValue);
                    break;
                default:
                    break;
            }
        }

        /// <summary>
        /// number of complete runs - e.g. a fully sequence buy-sell etc is done
        /// </summary>
        public virtual int Compeleted
        { get { return 0; } }

        /// <summary>
        /// how many time we have run
        /// </summary>
        public virtual int RunCount
        { get { return m_RunCount; } }

        /// <summary>
        /// Process a set of orders - typically on a timed basis - we
        /// expect this to be done by derived calsses
        /// </summary>
        /// <param name="?"></param>
        public virtual void ProcessOrderGroup(KaiTrade.Interfaces.OrderGroup myGroup)
        {
        }

        #endregion


        public void StartTimer()
        {
            if (m_TimerInterval > 0)
            {
                m_Timer = new System.Timers.Timer(m_TimerInterval);
                m_Timer.Elapsed += new ElapsedEventHandler(OnTimer);
                m_Timer.Interval = (double)m_TimerInterval;
                m_Timer.Enabled = true;
            }
        }

        public void StopTimer()
        {
            if (m_Timer != null)
            {
                m_Timer.Enabled = false;
            }
            m_Timer = null;
        }

        /// <summary>
        /// called on each timer tick - implimented by the base class
        /// </summary>
        protected virtual void TimerTick()
        {
        }

        private void OnTimer(object source, ElapsedEventArgs e)
        {
            try
            {
                expireOrders();
                TimerTick();
            }
            catch (Exception myE)
            {
                m_Log.Error("OnTimer", myE);
            }
        }

        private void expireOrders()
        {
            try
            {
                List<KaiTrade.Interfaces.Order> myProcessed = new List<KaiTrade.Interfaces.Order>();
                foreach (KaiTrade.Interfaces.Order myOrd in m_MonitorList)
                {
                    if (myOrd.Expiration <= DateTime.Now.Ticks)
                    {
                        Factory.Instance().AppFacade.CancelOrder(myOrd.Identity);
                        myProcessed.Add(myOrd);
                    }
                }

                // now remove any processed orders from the monitored list
                foreach (KaiTrade.Interfaces.Order myOrd in myProcessed)
                {
                    m_MonitorList.Remove(myOrd);
                }


            }
            catch (Exception myE)
            {
                m_Log.Error("expireOrders", myE);
            }
        }




    }
}
